const sequelize = require('sequelize');

const AppUtil = {
    isEquals(x, y) {
        // If both x and y are null or undefined and exactly the same
        if (x === y) {
            return true;
        }

        // If they are not strictly equal, they both need to be Objects
        if (!(x instanceof Object) || !(y instanceof Object)) {
            return false;
        }

        // They must have the exact same prototype chain, the closest we can do is
        // test.js the constructor.
        if (x.constructor !== y.constructor) {
            return false;
        }

        for(let p in x) {
            // Inherited properties were tested using x.constructor === y.constructor
            if (x.hasOwnProperty(p)) {
                // Allows comparing x[ p ] and y[ p ] when set to undefined
                if (!y.hasOwnProperty(p)) {
                    return false;
                }

                // If they have the same strict value or identity then they are equal
                if (x[p] === y[p]) {
                    continue;
                }

                // Numbers, Strings, Functions, Booleans must be strictly equal
                if (typeof (x[p]) !== "object") {
                    return false;
                }

                // Objects and Arrays must be tested recursively
                if (!AppUtil.isEquals(x[p], y[p])) {
                    return false;
                }
            }
        }

        for(let p in y) {
            // allows x[ p ] to be set to undefined
            if (y.hasOwnProperty(p) && !x.hasOwnProperty(p)) {
                return false;
            }
        }
        return true;
    },
    isEmpty(obj) {

        // null 和 undefined 是 "空的"
        if (obj === null) return true;

        /*eslint-disable-next-line*/
        if (obj === undefined) return true;
        //布尔值不可能为空, false 也不是空
        if (typeof obj === 'boolean') {
            return false;
        }

        /**
         * 如果类型为数字类型
         * 1. 如果是 NaN  看为空
         */

        if (typeof obj === "number") {
            return isNaN(obj);
        }
        if (typeof obj === "string") {
            return obj.trim().length === 0;
        }

        if (typeof obj === "function") {
            return false;
        }

        // Otherwise, does it have any properties of its own?
        // Note that this doesn't handle
        // toString and valueOf enumeration bugs in IE < 9
        /**
         * 类型为 object 可能为 date 类型, array 类型, object 类型
         * 1. 当 length 为 undefined 情况 可能为 object 或者 date 类型,如果是 date 类型不可能为空,如果是对象,那么遍历,如果有有自己的属性值那么该对象为非空
         * 2. 当有 length 的时候为数组,数组长度为 0 该数组为空,否则不为空
         */
        if (typeof obj === "object") {
            /*eslint-disable-next-line*/
            if (obj.length === undefined) {
                if (obj instanceof Date) {
                    return false;
                }
                for(const key in obj) {
                    if (Object.prototype.hasOwnProperty.call(obj, key)) return false;
                }
            } else {
                return obj.length === 0;
            }
        }

        return true;
    },
    requestFailed(message) {
        return {
            success: false,
            message
        }
    },
    validateParams(props = [], body) {
        let isValid = true, message = '';

        if (AppUtil.isEmpty(body)) {
            return {
                isValid: false,
                message: AppUtil.requestFailed(props.map(prop => `${prop.comment || prop.key}字段不能为空`).join(','))
            }
        }

        for(let index = 0; index < props.length; index++) {
            const prop = props[index];
            const value = body[prop.key];
            if (AppUtil.isEmpty(value)) {
                isValid = false;
                message = AppUtil.requestFailed(`${prop.comment || prop.key}不能为空`);
                break;
            }
            const type = typeof value;
            if (typeof prop.type === 'object') {
                if (prop.type.indexOf && prop.type.indexOf(type) === -1) {
                    isValid = false;
                    message = AppUtil.requestFailed(`${prop.key} 类型应为${prop.type},但接受为${type}`);
                    break;
                }
                continue
            }
            if (type !== prop.type) {
                isValid = false;
                message = AppUtil.requestFailed(`${prop.key} 类型应为${prop.type},但接受为${type}`);
                break;
            }

        }
        return {
            isValid,
            message
        }
    },
    getParameterByName(name, queryString) {
        name = name.replace(/[\[\]]/g, "\\$&");
        const regex = new RegExp("[?&]" + name + "(=([^&#]*)|&|#|$)"),
            results = regex.exec(queryString);
        if (!results) return null;
        if (!results[2]) return '';
        return decodeURIComponent(results[2].replace(/\+/g, " "));
    },
    getStartAndEndTime(startTime, endTime) {

        let isValid = true;
        const data = [];

        if (!AppUtil.isEmpty(startTime) && !AppUtil.isEmpty(endTime)) {
            if (new Date(startTime) > new Date(endTime)) {
                isValid = false
            }
        }

        if (!AppUtil.isEmpty(startTime) && AppUtil.isEmpty(endTime)) {
            data.push(new Date(startTime), new Date());
        }

        if (AppUtil.isEmpty(startTime) && !AppUtil.isEmpty(endTime)) {
            data.push(new Date(), new Date(endTime));
        }

        return {
            isValid,
            data
        }

    },
    queryOnlyIn(ids) {
        return {
            where: {
                id: {
                    [sequelize.Op.in]: ids
                }
            }
        }
    }
}

module.exports = AppUtil